package com.neucloud.da.edgeside.service.impl;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.neucloud.da.edgeside.model.entity.InfereceStatusEntity;
import com.neucloud.da.edgeside.model.entity.InferenceEntity;
import com.neucloud.da.edgeside.model.entity.ModelVersionEntity;
import com.neucloud.da.edgeside.model.enums.InferenceStatusEnum;
import com.neucloud.da.edgeside.model.enums.InferenceTypeEnum;
import com.neucloud.da.edgeside.model.exception.BusinessException;
import com.neucloud.da.edgeside.model.online.InferenceService;
import com.neucloud.da.edgeside.model.online.InferenceServiceStatus;
import com.neucloud.da.edgeside.model.online.InferenceServiceStatusAddress;
import com.neucloud.da.edgeside.service.IInferenceService;
import io.fabric8.kubernetes.api.model.Container;
import io.fabric8.kubernetes.api.model.EnvVar;
import io.fabric8.kubernetes.api.model.KubernetesResourceList;
import io.fabric8.kubernetes.client.KubernetesClient;
import io.fabric8.kubernetes.client.dsl.MixedOperation;
import io.fabric8.kubernetes.client.dsl.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;

@Slf4j
@Service
public class InferenceServiceImpl extends InferenceEngineService implements IInferenceService {
    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    KubernetesClient kubernetesClient;

    @Override
    public String getOnlineServiceId() {
        while (true){
            String onlineServiceId = RandomUtil.randomString(5);
            InferenceService inferenceService = getService(onlineServiceId);
            if(inferenceService == null){
                return onlineServiceId;
            }
        }
    }

    @Override
    public void createOnline(InferenceEntity inferenceEntity, ModelVersionEntity modelVersion) {
        createInference(inferenceEntity,modelVersion);
    }

    @Override
    public InfereceStatusEntity queryOnlineStatus(String onlineServiceId) {
        InfereceStatusEntity statusEntity = new InfereceStatusEntity();
        InferenceServiceStatus status = null;
        InferenceService inferenceService = getService(onlineServiceId);
        if(inferenceService == null){
            statusEntity.setStatus(InferenceStatusEnum.STOP.code);
        }
        statusEntity.setStatus(InferenceStatusEnum.STARTING.code);
        status = inferenceService.getStatus();
        if(status != null){
            InferenceServiceStatusAddress address = status.getAddress();
            log.info("synOnlineService status isvcOnlineServiceId:{} address:{}",onlineServiceId,address);
            if (address != null && StrUtil.isNotBlank(address.getURL())) {
                String inferenceName = InferenceTypeEnum.ONLINE.prefix + onlineServiceId;
                String modelName = inferenceName;
                Container container = inferenceService.getSpec().getTransformer().getContainers().get(0);
                List<EnvVar> env = container.getEnv();
                for (EnvVar envVar : env) {
                    if( envVar.getName().equals("model_name")){
                        modelName = envVar.getValue();
                        break;
                    }
                }
                statusEntity.setStatus(InferenceStatusEnum.RUNING.code);
                statusEntity.setApiUrl(status.getAddress().getURL().replace(inferenceName + ":", modelName + ":"));
            }
        }
        return statusEntity;
    }

    @Override
    public Boolean removeIsvcOnline(String isvcOnlineId) {
        String inferenceName = InferenceTypeEnum.ONLINE.prefix + isvcOnlineId;
        MixedOperation<InferenceService, KubernetesResourceList<InferenceService>, Resource<InferenceService>> inferenceServiceClient = kubernetesClient.resources(InferenceService.class);
        InferenceService inferenceService = inferenceServiceClient.inNamespace(namespace).withName(inferenceName).get();
        if(inferenceService != null){
            inferenceServiceClient.inNamespace(namespace).withName(inferenceName).delete();
        }
        return true;
    }

    private InferenceService getService(String onlineServiceId){
        String inferenceName = InferenceTypeEnum.ONLINE.prefix + onlineServiceId;
        MixedOperation<InferenceService, KubernetesResourceList<InferenceService>, Resource<InferenceService>> inferenceServiceClient = kubernetesClient.resources(InferenceService.class);
        InferenceService inferenceService = inferenceServiceClient.inNamespace(namespace).withName(inferenceName).get();
        return inferenceService;
    }

}
